/**
 *
 * This class transforms the node domain data structures into relevant outputs like:
 *
 *  - a JSON list/Tree(s) for viewing the attributes of nodes on a grid on UI on a web page
 *  - JSON Timeline for viewing on a timeline
 *  - Dependency 
 *
 */
class NodeDomainTransforms
{
    NodeDomain  nodeDomain
    String      outputFolderPath
    def logger = new Logger()


    NodeDomainTransforms(NodeDomain nodeDomain, String outputFolderPath)
    {
        this.nodeDomain = nodeDomain
        this.outputFolderPath = outputFolderPath

        logger.info("Creating output folder:"+outputFolderPath)

        // create the path if its not present
        new File(outputFolderPath).mkdirs()
    }


    /**
     * generates the graphical view
     */
    def generateGraphs()
    {
        logger.info("Generating NodeDomain graphs")

        Graphviz ggen = new Graphviz()
        ggen.newGraph(nodeDomain.name, true)
        
        def gNodes = [:]

        //------------------------------------------------
        // first, generate the whole Domain's graph
        nodeDomain.nodeList.nodes.each{ nodeKey, nodeObj ->
            gNodes.put(nodeObj.name, ggen.newGraphNode(nodeObj.name, nodeObj.name))
        }

        nodeDomain.nodeGraph.nodeEdges.each{ nodeEdge ->
            def gNodeA = gNodes.get(nodeEdge.nodeStartName)
            def gNodeB = gNodes.get(nodeEdge.nodeEndName)

            if(gNodeA!=null && gNodeB!=null)
                ggen.newGraphEdge(nodeEdge.caption, gNodeA, gNodeB)
        }

        def dotFilePath = ggen.genDotFileInFolder(nodeDomain.name.replace(" ", "_")+"_whole", nodeDomain.name)
        logger.info("\t|--Finished generating NodeDomain graph dot file")

        ggen.genDotImageInFolder(".", dotFilePath, nodeDomain.name)
        logger.info("\t|--Finished generating NodeDomain graph PNG image")

        //------------------------------------------------
        // now, generate each node's individual dependencies
        logger.info("Generating Each Node's dependencies graph dot file")


        def ctr = 1
        nodeDomain.nodeList.nodes.each { nodeKey, nodeObj ->
            ggen = new Graphviz()
            ggen.newGraph(nodeObj.name, true)
            def gNode = ggen.newGraphNode(nodeObj.name, nodeObj.name)

            nodeDomain.nodeGraph.nodeEdges.each{ nodeEdge ->
                if(nodeEdge.nodeStartName.equals(nodeObj.name))
                {
                    def gNodeA = gNode
                    def gNodeB = ggen.newGraphNode(nodeEdge.nodeEndName, nodeEdge.nodeEndName)

                    ggen.newGraphEdge(nodeEdge.caption, gNodeA, gNodeB)
                }
                else if(nodeEdge.nodeEndName.equals(nodeObj.name))
                {
                    def gNodeA = ggen.newGraphNode(nodeEdge.nodeStartName, nodeEdge.nodeStartName)
                    def gNodeB = gNode

                    ggen.newGraphEdge(nodeEdge.caption, gNodeA, gNodeB)
                }
            }

            logger.info("\t|--" + ctr + " Generating DOT file dependency graphs for Node:"+nodeObj.name)
            dotFilePath = ggen.genDotFileInFolder(nodeObj.name.replace(" ", "_"), outputFolderPath)

            logger.info("\t|--" + ctr + " Generating PNG file dependency graphs for Node:"+nodeObj.name)
            ggen.genDotImageInFolder(".", dotFilePath, outputFolderPath)
            ctr++
        }
    }


    /**
     * KEEPING GETS SEPARATE FROM WRITE TO FILE for serving dynamically thru a web server
     * generates the JSON js file for use by the Similie timeline widget
     */
    // gets the JSON-based format timeline data from the eventpts
    String getJsonTimeline()
    {
        def eventPts = []
        
        // collect all the eventPts first
        nodeDomain.nodeList.nodes.each{ nodeKey, nodeObj ->
            eventPts.add(nodeObj.eventPt)
        }
        
        def jsonTimeline = EventPtsUtil.getEventPtsJson(eventPts)
        
        return jsonTimeline
    }


    // writes the supplied timeline to a file
    void writeJsonTimelineToFile(String jsonTimeline)
    {
        logger.info( "writing event Pts to JSON file")
        File file = new File(new File("./" + nodeDomain.name + "/" + nodeDomain.name.replace(" ","_")+ "_timeline.js").getCanonicalPath())
        file.write(jsonTimeline.toString())
        logger.info( "finished writing BP eventPts to JSON file:"+file.toString())
    }

    
    // this gets timeline and writes it to a file
    void generateJsonTimeline()
    {
        def nodeDomainJsonTimeline = this.getJsonTimeline()
        this.writeJsonTimelineToFile(nodeDomainJsonTimeline)
    }


    /**
     * generates the JSON list for use by the ExtJS List view
     */
    String getJSONList()
    {
        /**
         * creates and returns the JS list for the list of services
         */
        logger.info("Creating the list views for the Domain:"+nodeDomain.name)

        def row = ""
        def rows = []
        def str1 = "var list=[\n"
        def str2 = "];\n"
        def str = ""
        def ctr = 1

        nodeDomain.nodeList.nodes.each{ nodeKey, nodeObj ->
            //eventPts.add(nodeObj.eventPt)
            //row = "['" + ctr + ".', '" + nodeObj.name + "'"
            row = "['${ctr}', '${nodeObj.name}', '${nodeObj.type}'"
            nodeObj.attrs.each { attrKey, attrValue ->
                row = row + ",'" + attrValue + "'"
            }

            row = row + "]"
            str = str + row + ",\n"
            //rows.add(row)
            ctr++
        }

        // create the full string
        str = str1 + str + str2

        def strBuf = new StringBuffer(str)
        strBuf.setCharAt(str.lastIndexOf(','), ' ' as char)

        return strBuf.toString()
    }

    
    void writeJsonListToFile(String jsonList)
    {
        logger.info( "writing Node List Attributes to JSON file")
        File file = new File(new File("./" + nodeDomain.name + "/" + nodeDomain.name.replace(" ","_")+ "_list.js").getCanonicalPath())
        file.write(jsonList.toString())
        logger.info( "finished writing Node List Attributes to JSON file"+file.toString())
    }
    
    
    /**
     * generates the list JSON file for the Node->Attribute values List view
     */
     void generateJsonList()
     {
         logger.info("Generating the List views for the Domain:"+nodeDomain.name)

         def listStr = getJSONList()
         writeJsonListToFile(listStr)
     }


    /**
     * generates the JSON list for use by the ExtJS Tree view
     */
    String getJSONTree()
    {
    }


    String copyHtmlFiles()
    {
        logger.info("Copying the html files for the domain")
        def filesList = ["index.html", "styles.css", nodeDomain.name + "_list.html", nodeDomain.name + "_timeline.html"]
        filesList.each { fileName ->
            logger.info("Copying "+fileName+ " to " + new File(this.outputFolderPath + "/" + fileName).getCanonicalPath() )

            Utils.copyFileLocalOrRemote(nodeDomain.sourceDocsLocation + "/" + fileName, this.outputFolderPath + "/" + fileName)
        }
    }


    static void main(args)
    {
        
        // ./rungroovy src/impl/NodeDomainTransforms.groovy MyDomain http://localhost:8080/
        // or ./rungroovy src/impl/NodeDomainTransforms.groovy MyDomain ./
        //NodeDomain nodeDomain = NodeDomainReader.initFromGenericExample()
        // make the folder if necessary
        // defaults
        String domainName = "MyDomain.backup"
        String docsLocation = "./MyDomain.backup"

        println args.size()
        if(args.size() == 1)
        {
            domainName = args[0]
        }
        else if(args.size() == 2)
        {
            domainName = args[0]
            docsLocation = args[1]
        }
        else
        {
            println "Usage:... <domainName> <docsLocation>\n for e.g. groovy ./src/impl/NodeDomainTransforms.groovy MyDomain ./MyDomain"
            println "or <domainName> <docsLocation>\n for e.g. groovy ./src/impl/NodeDomainTransforms.groovy MyDomain http://localhost:8080/soatimeline/MyDomain"
            return
        }

        def outputFolderPath = new File(ConfigVars.DOMAIN_GEN_HOME + "/" + domainName).getCanonicalPath()

        NodeDomain nodeDomain = NodeDomainReader.initFromDomainFolder(domainName, docsLocation)
        //NodeDomain nodeDomain = NodeDomainReader.initFromDomainFolder("MyDomain", "http://localhost:8080/soatimeline/MyDomain")
        NodeDomainTransforms transforms = new NodeDomainTransforms(nodeDomain, outputFolderPath)
        println("Generating Json Timeline")
        transforms.generateJsonTimeline()

        println("Generating Json List")
        println transforms.generateJsonList()

        println("Generating Graphs")
        transforms.generateGraphs()

        println("Copying Domain HTML files")
        transforms.copyHtmlFiles()
        
    }
}
